#ifndef CPU_H
#define CPU_H

#include "types.h"


#pragma pack(1)
typedef struct _segment_desc_t{
    uint16_t limit_low;
    uint16_t base_low;
    uint8_t base_mid;
    uint16_t attr;
    uint8_t base_high;
}segment_desc_t;
#pragma pack()

#define SEG_CPL0        (0<<0)
#define SEG_CPL3        (3<<0)

//the attribute of segment descriptor
#define SEG_G           (1<<15) //Granularity(0=1B,1=4KB)
#define SEG_D           (1<<14)  //Default operation size(0=16bit,1=32bit segment)
//#define SEG_L           (1<<13) //64bit code segment(IA-32e mode only)
//#define SEG_AVL         (1<<12) //available for system use
#define SEG_P           (1<<7) //segment present

#define SEG_DPL0        (0<<5)//descriptor privilege level
#define SEG_DPL3        (3<<5)


#define SEG_S_SYSTEM           (0<<4) //descriptor type(0=system,1=code/data)
#define SEG_S_CODE_DATA        (1<<4)

#define SEG_TYPE_DATA        (0<<3) //segment type(0=data,1=code)
#define SEG_TYPE_CODE        (1<<3)

//#define SEG_TYPE_DATA_EXPAND_DOWN (1<<2)
#define SEG_TYPE_DATA_WRITE       (1<<1)
//#define SEG_TYPE_DATA_ACCESSED    (1<<0)

//#define SEG_TYPE_CODE_CONFORMING  (1<<2)
#define SEG_TYPE_CODE_READ        (1<<1)
//#define SEG_TYPE_CODE_ACCESSED    (1<<0)

//goto tss descriptor
#define SEG_TYPE_TSS        (1<<0 | 1<<3)
#define SEG_TYPE_TSS_BUSY   (1<<1)

//about tss,task_stack_segment
typedef struct _tss_t{
   uint32_t pre_task_link;
   uint32_t esp0,ss0,esp1,ss1,esp2,ss2;
   uint32_t cr3;
   uint32_t eip,eflags;
   uint32_t eax,ecx,edx,ebx,esp,ebp,esi,edi;
   uint32_t es,cs,ss,ds,fs,gs;
   uint32_t ldt;
   uint32_t iomap;
}tss_t;

//about eflags
#define EFLAGS_DEFAULT    (1<<1)
#define EFLAGS_IF         (1<<9)

void segment_desc_set(int selector,uint32_t base,uint32_t limit,uint16_t attr);
void cpu_init();
int gdt_alloc_desc();
void switch_to_tss(int tss_selector);

void gdt_free_selector(int selector);
#endif // !CPU_H